from typing import List
import zlib
import KBEngine
import KBEDebug as log
import time
import datetime


"""
在这个文件里面写能在其他游戏中能复用的代码逻辑
"""


def nickName2IntArr(nickNameHexStr):
    # 将字节码字符串转为字节码数组
    bytesArr = bytearray.fromhex(nickNameHexStr)
    # 将字节码数组转为十进制数组
    nickNameArr = [b for b in bytesArr]
    return nickNameArr


def toInt(num):
    """
    将浮点数四舍五入后再取整
    """
    return int(round(num))


def convertListUUID(lst: List[any], uuidKeys: List[str]):
    """
    转化带UINT64或者INT64的列表

    只能是单层列表，不能有嵌套列表
    """
    # newLst = copy.deepcopy(lst)  # KBEngine的基础类型不支持
    newLst = []
    for e in lst:
        o = {}
        for k in e:
            if k in uuidKeys:
                o[k] = str(e[k])
            else:
                o[k] = e[k]

        newLst.append(o)

    return newLst


def convert2bytes(obj: any, uuidKeys: List[str] = None) -> bytes:
    """
    将python的字典转成bytes并压缩
    """
    json_str = None
    if uuidKeys is not None:
        newObj = {}
        for k in obj:
            newObj[k] = obj[k]
            if k in uuidKeys:
                newObj[k] = str(obj[k])
    elif isinstance(obj, str):
        json_str = obj
    else:
        json_str = str(obj)
    binary_s = zlib.compress(bytes(json_str, 'utf-8'))
    return binary_s


def createSingletonEntity(entityName: str, params: dict = {}):
    """
    创建全局唯一实体。必须声明好py脚本和def文件。是用KBEngine.globalData[entityName]获取实体
    还是用KBEngine.baseAppData[entityName]获取实体需要自己在实体脚本中写明。

    如果明确该实体只在BaseApp中共享数据则用KBEngine.baseAppData。

    eg.
        Utils.createSingletonEntity('Lobby', {})
    """

    def sqlCallback(result, rows, insertid, error):
        if error:
            log.ERROR_MSG('Utils::createSingletonEntity %s error: %s' % (entityName, error))
        else:
            if len(result) > 0:
                dbid = int(result[0][0])
                KBEngine.createEntityFromDBID(entityName, dbid)
            else:
                entity = KBEngine.createEntityLocally(entityName, params)
                if entity is not None:
                    entity.writeToDB()
                else:
                    log.ERROR_MSG('Utils::createSingletoneEntity create %s entity error' % entityName)

            log.DEBUG_MSG('Utils::createSingletoneEntity %s, result: %s' % (entityName, str(result)))

    sql = 'select id from tbl_%s;' % entityName
    KBEngine.executeRawDatabaseCommand(sql, sqlCallback)


def isCrossDay(check_time):
    """
    判断是否跨天
    """
    t1 = int(time.time())
    dt1 = datetime.datetime.fromtimestamp(t1)
    dt2 = datetime.datetime.fromtimestamp(check_time)

    return dt1.date() != dt2.date()


def crossDayCount(check_time):
    t1 = int(time.time())
    dt1 = datetime.datetime.fromtimestamp(t1)
    dt2 = datetime.datetime.fromtimestamp(check_time)
    diff = dt1.date() - dt2.date()
    return diff.days


def isCrossWeek(check_time):
    """
    判断是否跨周
    """
    dt1 = datetime.datetime.now()
    dt2 = datetime.datetime.fromtimestamp(check_time)
    return dt1.isocalendar()[1] != dt2.isocalendar()[1]


def isCrossMonth(check_time):
    """
    判断是否跨月
    """
    dt1 = datetime.datetime.now()
    dt2 = datetime.datetime.fromtimestamp(check_time)
    now_month = dt1.month
    cur_month = dt2.month
    return now_month != cur_month


def countdownTomorrow():
    now = datetime.datetime.now()
    today_begin = datetime.datetime(now.year, now.month, now.day, 0, 0, 0)
    tomorrow_begin = today_begin + datetime.timedelta(days=1)
    rest_seconds = (tomorrow_begin - now).seconds
    return rest_seconds


def countdownNextMonday():
    # 获取当前时间
    now = datetime.datetime.now()

    # 计算下周一0点的时间
    # 首先计算今天是星期几（星期一是0，星期二是1，...，星期日是6）
    days_until_monday = (7 - now.weekday()) % 7
    if days_until_monday == 0:
        days_until_monday = 7  # 如果今天是星期一，就计算到下一个星期一

    # 获取下周一0点的时间
    next_monday = (now + datetime.timedelta(days=days_until_monday)).replace(hour=0, minute=0, second=0, microsecond=0)

    # 计算时间差
    time_difference = next_monday - now

    # 将时间差转换为秒
    seconds_until_next_monday = int(time_difference.total_seconds())

    log.DEBUG_MSG(f'距离下周一还有{seconds_until_next_monday} 秒')
    return seconds_until_next_monday
